<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>Bar 3D - ECHARTS-GL</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes"> <!-- Fullscreen Landscape on iOS -->
    <link rel="stylesheet" href="./common.css">
</head>
<body>
<div id="main"></div>
<script src="../node_modules/echarts/dist/echarts.js"></script>
<script src="../dist/echarts-gl.js"></script>
<script src="lib/jquery.min.js"></script>
<script src="js/commonUI.js"></script>
<script>
    var UPDATE_DURATION = 100;

    var chart = echarts.init(document.getElementById('main'));

    window.AudioContext = window.AudioContext || window.webkitAudioContext;

    var audioContext = new AudioContext();

    var oReq = new XMLHttpRequest();
    oReq.open('GET', 'asset/roll-it-up.mp3', true);
    oReq.responseType = 'arraybuffer';

    oReq.onload = function (e) {
        audioContext.decodeAudioData(oReq.response, initVisualizer);
    };
    oReq.send();

    function initVisualizer(audioBuffer) {
        inited = true;

        var source = audioContext.createBufferSource();
        source.buffer = audioBuffer;

        // Must invoked right after click event
        if (source.noteOn) {
            source.noteOn(0);
        } else {
            source.start(0);
        }

        var analyzer = audioContext.createAnalyser();
        var gainNode = audioContext.createGain();
        analyzer.fftSize = 4096;

        gainNode.gain.value = 1;
        source.connect(gainNode);
        gainNode.connect(analyzer);
        analyzer.connect(audioContext.destination);

        var frequencyBinCount = analyzer.frequencyBinCount;
        var dataArray = new Uint8Array(frequencyBinCount);

        var item = [];
        var size = 50;


        var beta = 0;

        function update() {
            analyzer.getByteFrequencyData(dataArray);

            var data = new Float64Array(size * size * 3);
            var off = 0;
            for (var i = 0; i < size * size; i++) {
                var x = i % size;
                var y = Math.floor(i / size);
                var dx = x - size / 2;
                var dy = y - size / 2;

                var angle = Math.atan2(dy, dx);
                if (angle < 0) {
                    angle = Math.PI * 2 + angle;
                }
                var dist = Math.sqrt(dx * dx + dy * dy);
                var idx = Math.min(
                    frequencyBinCount - 1, Math.round(angle / Math.PI / 2 * 60 + dist * 60) + 100
                );

                var val = Math.pow(dataArray[idx] / 100, 3);

                data[off++] = x;
                data[off++] = y;
                data[off++] = Math.max(val, 0.1);
            }

            console.time('update');
            chart.setOption({
                grid3D: {
                    viewControl: {
                        beta: beta,
                        alpha: Math.sin(beta / 10 + 40) * (beta % 10 + 5) / 15 * 30 + 30,
                        distance: Math.cos(beta / 50 + 20) * (beta % 10 + 5) / 15 * 50 + 80,
                        animationDurationUpdate: UPDATE_DURATION,
                        animationEasingUpdate: 'linear'
                    }
                },
                series: [{
                    dimensions: ['x', 'y', 'z'],
                    data: data
                }]
            });
            beta += 2;
            console.timeEnd('update');

            setTimeout(update, UPDATE_DURATION);
        };

        update();
    }

    chart.setOption({
        tooltip: {},
        visualMap: {
            show: false,
            min: 0.1,
            max: 4,
            inRange: {
                color: ['#010103', '#2f490c', '#b0b70f', '#fdff44', '#fff']
            }
        },
        xAxis3D: {
            type: 'value'
        },
        yAxis3D: {
            type: 'value'
        },
        zAxis3D: {
            type: 'value',
            min: -6,
            max: 6
        },
        grid3D: {
            show: false,
            environment: '#000',
            viewControl: {
                distance: 100
            },
            postEffect: {
                enable: true,
                FXAA: {
                    enable: true
                }
            },
            light: {
                main: {
                    shadow: true,
                    intensity: 10,
                    quality: 'high'
                },
                ambientCubemap: {
                    texture: 'asset/canyon.hdr',
                    exposure: 0,
                    diffuseIntensity: 0.2
                }
            }
        },
        series: [{
            type: 'bar3D',
            silent: true,
            shading: 'lambert',
            data: [],
            barSize: 1,
            lineStyle: {
                width: 4
            },
            // animation: false,
            animationDurationUpdate: UPDATE_DURATION
        }]
    });

    window.addEventListener('resize', function () {
        chart.resize();
    });

</script>
</body>
</html>
